package de.iritgo.skillfull.entity.command;

import java.awt.Point;

import de.iritgo.skillfull.component.visitor.MoveAnimationVisitor;
import de.iritgo.skillfull.component.visitor.MoveFieldVisitor;
import de.iritgo.skillfull.component.visitor.MoveRotationVisitor;
import de.iritgo.skillfull.component.visitor.PositionVisitor;
import de.iritgo.skillfull.component.visitor.RotationVisitor;
import de.iritgo.skillfull.entity.Command;
import de.iritgo.skillfull.entity.Entity;
import de.iritgo.skillfull.entity.Entity.DST_FIELD;

public class PlayerMovementCommand implements Command 
{
	public static final int STOP = 1;
	
	private Entity entity;
	private boolean done;
	private MoveFieldVisitor moveFieldVisitor;
	private Point oldPosition;
	private Point destPosition;
	private RotationVisitor rotationVisitor;
	private DST_FIELD dstField;

	private int special;

	private MoveAnimationVisitor moveAnimationVisitor;

	private float looking;

	private MoveRotationVisitor moveRotationVisitor;
	
	public PlayerMovementCommand (Entity entity, Point dest, float looking)
	{	
		this.entity = entity;
		this.destPosition = dest;
		this.looking = looking;
		this.done = false;
		oldPosition = entity.getPosition ();
		this.moveFieldVisitor = new MoveFieldVisitor (dest);
		this.rotationVisitor = new RotationVisitor (looking);
		this.moveAnimationVisitor = new MoveAnimationVisitor (true);
	}
	
	public PlayerMovementCommand (Entity entity, Entity.DST_FIELD dst)
	{	
		this.entity = entity;
		this.done = false;
		oldPosition = entity.getPosition ();
		this.destPosition = getPositionByDstField(dst, oldPosition);
		this.moveFieldVisitor = new MoveFieldVisitor (destPosition);
		this.moveRotationVisitor = new MoveRotationVisitor (destPosition);
		this.moveAnimationVisitor = new MoveAnimationVisitor (true);
	}

	public PlayerMovementCommand(Entity entity, int special) 
	{
		this.special = special;
		this.entity = entity;
		this.done = false;
		oldPosition = entity.getPosition ();
		this.moveFieldVisitor = new MoveFieldVisitor (special);
		this.moveRotationVisitor = new MoveRotationVisitor (special);
		this.moveAnimationVisitor = new MoveAnimationVisitor (special);
	}
	
	public String getName ()
	{
		return special == 0 ? "Move" : "Stop"; 
	}
	

	private Point getPositionByDstField(Entity.DST_FIELD dst, Point currentDst) 
	{
		int x = (int) currentDst.x;
		int y = (int) currentDst.y;
		int dstX = (int) currentDst.x;
		int dstY = (int) currentDst.y;
		this.dstField = dst;
		
		switch (dst)
		{
			case NORTH:
			{
				dstY = (int) x - 32; //Get from MapService
				break;
			}
			case NORTHWEST:
			{
				dstY = (int) x - 32; //Get from MapService
				dstX = (int) y + 32; //Get from MapService
				break;
			}
			case WEST:
			{
				dstX = (int) x + 32; //Get from MapService
				break;
			}
			case SOUTHWEST:
			{
				dstY = (int) y + 32; //Get from MapService
				dstX = (int) x + 32; //Get from MapService
				break;
			}
			case SOUTH:
			{
				dstY = (int) y + 32; //Get from MapService
				break;
			}
			case SOUTHEAST:
			{
				dstY = (int) y + 32; //Get from MapService
				dstX = (int) x - 32; //Get from MapService
				break;
			}
			case EAST:
			{
				dstX = (int) x - 32; //Get from MapService
				break;
			}
			case NORTHEAST:
			{
				dstY = (int) y - 32; //Get from MapService
				dstX = (int) x - 32; //Get from MapService
				break;
			}
		}
		Point dstPosition = new Point (dstX, dstY);
		return dstPosition;
	}

	@Override
	public boolean canPerform () 
	{
		return true;
	}

	@Override
	public void perform (int delta) 
	{
		entity.accept (moveFieldVisitor);
		if (moveRotationVisitor == null)
		{
			entity.accept (rotationVisitor);
		}
		else
		{
			entity.accept (moveRotationVisitor);
		}
		entity.accept (moveAnimationVisitor);
		done = moveFieldVisitor.isDone ();
	}
	
	public void stop() 
	{
		done = true;
	}

	@Override
	public Command getUndoCommand () 
	{
		if (special == STOP || dstField == null)
		{
			return new MoveFieldCommand (entity, special);
		}
		
		int pos = dstField.ordinal ();
		pos = pos + 4;
		if (pos > 8)
		{
			pos = pos - 8;
		}
		return new MoveFieldCommand (entity, Entity.DST_FIELD.values()[pos]);
	}

	@Override
	public boolean isDone () 
	{
		return done;
	}
}
